import threading
import time
import queue
import platform
from typing import Optional, Callable, Dict, Any
from global_settings import debug_print


class SerialWorker:
    """跨平台串口通信工作器"""
    
    def __init__(self, serial_manager, protocol_parser):
        self.current_protocol = None
        self.serial_manager = serial_manager
        self.protocol_parser = protocol_parser
        self.command_queue = queue.Queue()
        self.is_running = False
        self.worker_thread = None
        self.callbacks = {}
        self.current_command = None
        self.last_command_time = 0
        
        # 平台特定的时间参数
        if platform.system() == "Windows":
            self.min_command_interval = 0.025  # Windows 需要稍长的间隔
        elif platform.system() == "Linux":
            self.min_command_interval = 0.015  # Linux 响应较快
        else:  # macOS
            self.min_command_interval = 0.020  # macOS 中等间隔

    def _get_platform_specific_wait_time(self, count: int, protocol: str = "") -> float:
        """获取平台特定的等待时间"""
        base_time = 0.1
        
        if platform.system() == "Windows":
            # Windows 串口响应较慢
            base_time = 0.15
            per_register = 0.008
        elif platform.system() == "Linux":
            # Linux 串口响应较快
            base_time = 0.08
            per_register = 0.005
        else:  # macOS
            base_time = 0.12
            per_register = 0.006
            
        # 协议特定的调整
        if "同飞" in protocol:
            base_time += 0.1
            per_register += 0.005
            
        wait_time = base_time + count * per_register
        return min(wait_time, 1.0)  # 最大不超过1秒

    def _platform_specific_serial_delay(self):
        """平台特定的串口延迟"""
        if platform.system() == "Windows":
            time.sleep(0.015)
        elif platform.system() == "Linux":
            time.sleep(0.008)
        else:  # macOS
            time.sleep(0.010)

    def start(self):
        """启动工作线程"""
        if self.is_running:
            return

        self.is_running = True
        self.worker_thread = threading.Thread(target=self._worker_loop, daemon=True)
        self.worker_thread.start()
        debug_print(f"串口工作线程已启动 ({platform.system()})")

    def stop(self):
        """停止工作线程"""
        self.is_running = False
        if self.worker_thread and self.worker_thread.is_alive():
            self.worker_thread.join(timeout=2.0)
        debug_print("串口工作线程已停止")

    # 保持原有接口不变
    def send_command(self, command_type: str, address: int, value: Any = None,
                     callback: Optional[Callable] = None) -> bool:
        """发送命令到工作队列 - 接口保持不变"""
        if not self.is_running:
            debug_print("工作线程未运行")
            return False

        command_id = f"{command_type}_{address}_{time.time()}"
        command = {
            'id': command_id,
            'type': command_type,
            'address': address,
            'value': value,
            'timestamp': time.time()
        }

        if callback:
            self.callbacks[command_id] = callback

        try:
            self.command_queue.put(command, timeout=0.5)
            return True
        except queue.Full:
            debug_print("命令队列已满")
            return False

    def read_registers_batch(self, register_groups: list, callback: Optional[Callable] = None) -> bool:
        """批量读取寄存器组 - 接口保持不变"""
        if not self.is_running:
            return False

        command_id = f"read_batch_{time.time()}"
        command = {
            'id': command_id,
            'type': 'READ_BATCH',
            'groups': register_groups,
            'protocol': self.current_protocol.get("name", "") if self.current_protocol else "",
            'timestamp': time.time()
        }

        if callback:
            self.callbacks[command_id] = callback

        try:
            self.command_queue.put(command, timeout=0.5)
            return True
        except queue.Full:
            debug_print("命令队列已满")
            return False

    def _worker_loop(self):
        """工作线程主循环 - 优化跨平台支持"""
        platform_name = platform.system()
        debug_print(f"工作线程运行在 {platform_name} 平台")
        
        while self.is_running:
            try:
                # 平台特定的队列获取超时
                queue_timeout = 0.05
                try:
                    command = self.command_queue.get(timeout=queue_timeout)
                except queue.Empty:
                    continue

                self.current_command = command
                self._process_command(command)
                self.command_queue.task_done()

            except Exception as e:
                debug_print(f"工作线程错误: {str(e)}")
                # 平台特定的错误恢复时间
                if platform.system() == "Windows":
                    time.sleep(0.1)
                else:
                    time.sleep(0.05)

    def _process_command(self, command: Dict[str, Any]):
        """处理单个命令 - 优化跨平台支持"""
        try:
            command_type = command['type']

            # 确保命令间隔，避免过快发送
            current_time = time.time()
            time_since_last = current_time - self.last_command_time
            if time_since_last < self.min_command_interval:
                time.sleep(self.min_command_interval - time_since_last)

            if command_type == 'READ_BATCH':
                self._process_read_batch(command)
            elif command_type == 'READ_REGISTERS':
                self._process_read_registers(command)
            elif command_type == 'WRITE_REGISTER':
                self._process_write_register(command)
            else:
                debug_print(f"未知命令类型: {command_type}")

            self.last_command_time = time.time()

        except Exception as e:
            debug_print(f"处理命令失败: {str(e)}")
            self._invoke_callback(command['id'], {'success': False, 'error': str(e)})

    def _process_read_batch(self, command: Dict[str, Any]):
        """处理批量读取命令 - 优化跨平台支持"""
        groups = command['groups']
        protocol = command.get('protocol', '')
        all_results = {}
        failed_reads = []

        total_groups = len(groups)

        for i, group in enumerate(groups):
            if not self.is_running:
                break

            start_addr = group['start']
            count = group['count']
            expected_registers = group['registers']

            debug_print(f"读取分组 {i + 1}/{total_groups}: 0x{start_addr:04X}({start_addr}), 数量={count}")

            # 发送读取命令
            hex_command = self.protocol_parser.format_read_command(start_addr, count)

            if not self.serial_manager.write_data(hex_command):
                debug_print(f"发送分组 {i} 命令失败")
                failed_reads.extend(expected_registers)
                continue

            # 平台和协议特定的等待时间
            wait_time = self._get_platform_specific_wait_time(count, protocol)
            time.sleep(wait_time)

            # 读取响应
            response = self.serial_manager.read_data(timeout=0.5)

            if response and len(response) >= 5:
                if response[1] & 0x80:  # 异常响应
                    error_code = response[2] if len(response) > 2 else 0
                    debug_print(f"分组 {i} 异常响应: 错误码 0x{error_code:02X}")
                    failed_reads.extend(expected_registers)
                else:
                    # 正常响应
                    parsed_data = self.protocol_parser.parse_response(response, start_addr, count)
                    debug_print(f"分组 {i} 成功: 解析到 {len(parsed_data)} 个寄存器")

                    # 过滤出我们关心的寄存器
                    filtered_data = {}
                    for addr in expected_registers:
                        addr_str = str(addr)
                        if addr_str in parsed_data:
                            filtered_data[addr_str] = parsed_data[addr_str]

                    all_results.update(filtered_data)

                    # 进度回调
                    progress_result = {
                        'success': True,
                        'data': filtered_data,
                        'progress': (i + 1) / total_groups,
                        'is_complete': False
                    }
                    self._invoke_callback(command['id'], progress_result)
            else:
                debug_print(f"分组 {i} 无响应或响应不完整")
                failed_reads.extend(expected_registers)

            # 平台特定的组间延迟
            self._platform_specific_serial_delay()

        # 重试失败的读取
        if failed_reads:
            debug_print(f"开始重试 {len(failed_reads)} 个失败的寄存器")
            retry_results = self._retry_failed_registers_smart(failed_reads, protocol)
            all_results.update(retry_results)

        # 最终回调
        final_failed_count = len([addr for addr in failed_reads if str(addr) not in all_results])
        self._invoke_callback(command['id'], {
            'success': True,
            'data': all_results,
            'failed_count': final_failed_count,
            'is_complete': True
        })

    # 其他方法保持不变，但会使用新的平台特定方法...
    # _retry_failed_registers_smart, _read_register_range_robust 等方法需要相应调整
    
    def _retry_failed_registers_smart(self, failed_addresses, protocol=""):
        """智能重试失败的寄存器 - 支持平台特定优化"""
        if not failed_addresses:
            return {}

        retry_results = {}

        # 平台特定的重试分组大小
        if platform.system() == "Windows":
            max_group_size = 6  # Windows 使用较小的分组
        elif platform.system() == "Linux":
            max_group_size = 10  # Linux 可以处理较大的分组
        else:  # macOS
            max_group_size = 8

        # 按小分组重试
        failed_addresses.sort()
        small_groups = []

        current_group = []
        for addr in failed_addresses:
            if not current_group:
                current_group.append(addr)
            elif len(current_group) < max_group_size and addr - current_group[0] < max_group_size:
                current_group.append(addr)
            else:
                small_groups.append(current_group.copy())
                current_group = [addr]

        if current_group:
            small_groups.append(current_group)

        # 重试每个小分组
        for group in small_groups:
            if len(group) == 1:
                # 单个寄存器重试
                result = self._read_single_register_robust(group[0], protocol)
                if result:
                    retry_results.update(result)
            else:
                # 小分组重试
                start_addr = group[0]
                count = group[-1] - group[0] + 1
                result = self._read_register_range_robust(start_addr, count, group, protocol)
                if result:
                    retry_results.update(result)

            # 平台特定的分组间延迟
            self._platform_specific_serial_delay()

        return retry_results

    def _read_register_range_robust(self, start_addr, count, expected_registers, protocol=""):
        """鲁棒的寄存器范围读取 - 支持平台特定优化"""
        hex_command = self.protocol_parser.format_read_command(start_addr, count)

        if not self.serial_manager.write_data(hex_command):
            return {}

        # 平台特定的等待时间
        wait_time = self._get_platform_specific_wait_time(count, protocol)
        time.sleep(wait_time)

        response = self.serial_manager.read_data(timeout=0.5)

        if response and len(response) >= 5 and not (response[1] & 0x80):
            parsed_data = self.protocol_parser.parse_response(response, start_addr, count)
            # 过滤出我们关心的寄存器
            filtered_data = {}
            for addr in expected_registers:
                addr_str = str(addr)
                if addr_str in parsed_data:
                    filtered_data[addr_str] = parsed_data[addr_str]
                    debug_print(f"重试成功: 寄存器 0x{addr:04X}")
            return filtered_data

        return {}

    def _read_single_register_robust(self, address, protocol=""):
        """鲁棒的单寄存器读取"""
        return self._read_register_range_robust(address, 1, [address], protocol)

    def _process_read_registers(self, command: Dict[str, Any]):
        """处理读取寄存器命令 - 支持平台特定优化"""
        address = command['address']
        count = command.get('value', 1)

        hex_command = self.protocol_parser.format_read_command(address, count)

        if not self.serial_manager.write_data(hex_command):
            self._invoke_callback(command['id'], {'success': False, 'error': '发送命令失败'})
            return

        # 平台特定的等待时间
        wait_time = self._get_platform_specific_wait_time(count, "")
        time.sleep(wait_time)

        response = self.serial_manager.read_data(timeout=0.3)

        if response:
            parsed_data = self.protocol_parser.parse_response(response, address, count)
            self._invoke_callback(command['id'], {
                'success': True,
                'data': parsed_data
            })
        else:
            self._invoke_callback(command['id'], {'success': False, 'error': '无响应'})

    def _process_write_register(self, command: Dict[str, Any]):
        """处理写入寄存器命令 - 支持平台特定优化"""
        address = command['address']
        value = command['value']

        hex_command = self.protocol_parser.format_write_command(address, value)

        if not self.serial_manager.write_data(hex_command):
            self._invoke_callback(command['id'], {'success': False, 'error': '发送命令失败'})
            return

        # 平台特定的写入等待时间
        if platform.system() == "Windows":
            write_wait = 0.25
        elif platform.system() == "Linux":
            write_wait = 0.15
        else:  # macOS
            write_wait = 0.20
            
        time.sleep(write_wait)
        response = self.serial_manager.read_data(timeout=0.3)

        if response:
            parsed_data = self.protocol_parser.parse_response(response)
            self._invoke_callback(command['id'], {
                'success': True,
                'data': parsed_data
            })
        else:
            self._invoke_callback(command['id'], {'success': False, 'error': '无响应'})

    def _invoke_callback(self, command_id: str, result: Dict[str, Any]):
        """调用回调函数 - 保持不变"""
        if command_id in self.callbacks:
            try:
                self.callbacks[command_id](result)
                # 如果是最终完成回调，删除回调函数
                if result.get('is_complete', True):
                    del self.callbacks[command_id]
            except Exception as e:
                debug_print(f"回调执行失败: {str(e)}")